﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "IDocument.h"
#include "ParameterType.h"
#include "IGraphicsMaterial.h"
#include "IStandardCodeItem.h"
#include "UnitUniIdentities.h"
#include "IParameterValueInt.h"
#include "IParameterDefinition.h"
#include "IParameterValueDouble.h"
#include "IParameterValueString.h"
#include "IParameterValueStorage.h"
#include "IParameterValueElementId.h"
#include "IStandardCodeSystemProxy.h"
#include "IParameterDefinitionLibrary.h"

#include "ParameterDisplayEditbox.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace Sample;

ParameterDisplayEditbox::ParameterDisplayEditbox(const UniIdentity& uid):
    m_paramDefUid(uid)
{

}

ParameterDisplayEditbox::~ParameterDisplayEditbox()
{

}

std::wstring ParameterDisplayEditbox::GetDisplayStringByValue( const IDocument* pDoc, const IParameterValueStorage* pValue ) const
{
    std::wstring res;

    DBG_WARN_AND_RETURN_UNLESS(pDoc, res, L"无效的参数pDoc",L"GDMP",L"2023-10-20");
    DBG_WARN_AND_RETURN_UNLESS(pValue, res, L"无效的参数pValue",L"GDMP",L"2023-10-20");

    const IParameterDefinitionLibrary* pParaDefLib = IParameterDefinitionLibrary::Get(pDoc);
    DBG_WARN_AND_RETURN_UNLESS(pParaDefLib, res, L"paramLib为空！",L"GDMP",L"2023-10-20");

    const IParameterDefinition* pd = pParaDefLib->GetParameterDefinitionByUid(GetParameterDefinitionUid());
    DBG_WARN_AND_RETURN_UNLESS(pd, res, L"paramLib为空！",L"GDMP",L"2023-10-20");

    UniIdentity ptId = pd->GetParameterTypeId();
    if (ptId == PARAMETER_TYPE(Number) ||
        ptId == PARAMETER_TYPE(Length) ||
        ptId == PARAMETER_TYPE(Float))
    {
        // 存在外部构件的参数单位类型是LENGTH，但是存储类型是INT，比如Revit。
        // 以后遇到其它存储类型可以再加
        if (const IParameterValueInt* pPVSInt = quick_cast<const IParameterValueInt>(pValue))
        {
            res = StringUtil::ToWString(pPVSInt->GetValue());
        }
        else
        {
            if (const IParameterValueDouble* pPVSDouble = quick_cast<const IParameterValueDouble>(pValue))
            {
                res = StringUtil::ToWString((double)pPVSDouble->GetValue(), 3);
            }
        }
    }
    else if (ptId == PARAMETER_TYPE(Area))
    {
        if (const IParameterValueDouble* pPVSDouble = quick_cast<const IParameterValueDouble>(pValue))
        {
            // 单位转化为平方米
            double area = pPVSDouble->GetValue() / 1E6;
            res = StringUtil::ToWString(area, 3) + GBMP_TR(L" m²");
        }
    }
    else if (ptId == PARAMETER_TYPE(Volume))
    {
        if (const IParameterValueDouble* pPVSDouble = quick_cast<const IParameterValueDouble>(pValue))
        {
            // 单位转化为立方米
            double volume = pPVSDouble->GetValue() / 1E9;
            res = StringUtil::ToWString(volume, 3) + GBMP_TR(L" m³");
        }
    }
    else if (ptId == PARAMETER_TYPE(Angle))
    {
        if (const IParameterValueDouble* pPVSDouble = quick_cast<const IParameterValueDouble>(pValue))
        {
            res = StringUtil::ToWString((double)(pPVSDouble->GetValue() * 180 / gcmp::Constants::MATH_PI), 2);
            res += L"°";
        }
    }
    else if (ptId == PARAMETER_TYPE(Text))
    {
        if (const IParameterValueString* pPVSString = quick_cast<const IParameterValueString>(pValue))
        {
            res = pPVSString->GetValue();
        }
    }
    else if (ptId == PARAMETER_TYPE(Material))
    {
        if (const IParameterValueElementId* pPVSModelId = quick_cast<const IParameterValueElementId>(pValue))
        {
            ElementId idElement = pPVSModelId->GetValue();
            res = GBMP_TR(L"<按类别>");
            // 取出对应Element的名称进行显示
            const IGraphicsMaterial* graphicsMaterial = quick_cast<IGraphicsMaterial>(pDoc->GetElement(idElement));
            if (graphicsMaterial != nullptr)
            {
                graphicsMaterial->GetMaterialInstanceName(res);
            }
        }
    }
    else if (ptId == PARAMETER_TYPE(StandardCodeReference))
    {
        if (const IParameterValueString* pPVSString = quick_cast<const IParameterValueString>(pValue))
        {
            const std::wstring& value = pPVSString->GetValue();
            const IStandardCodeItem* pCodeItem = IStandardCodeSystemProxy::Get()->GetStandardCodeItemByCode(value);
            if (pCodeItem)
            {
                res = pCodeItem->GetCodeName();
            }
        }
    }
    else if (ptId == PARAMETER_TYPE(ValueList))
    {
        if (const IParameterValueString* pPVSString = quick_cast<const IParameterValueString>(pValue))
        {
            res = pPVSString->GetValue();
            // 枚举
            if (pd->IsStandard())
            {
                if (ParameterStorageType::StandardCodeReference == pd->GetStorageType())
                {
                    if (const IStandardCodeItem* pCodeItem = IStandardCodeSystemProxy::Get()->GetStandardCodeItemByCode(res))
                    {
                        res = pCodeItem->GetCodeName();
                    }
                }
            }
        }
    }

    return res;
}

OwnerPtr<IParameterValueStorage> ParameterDisplayEditbox::GetValueByDisplayString( const IDocument* pDoc, const std::wstring& displayString ) const
{
    OwnerPtr<IParameterValueStorage> oRes;

    DBG_WARN_AND_RETURN_UNLESS(pDoc, oRes, L"无效的参数pDoc",L"GDMP",L"2023-10-20");

    const IParameterDefinitionLibrary* pParaDefLib = IParameterDefinitionLibrary::Get(pDoc);
    DBG_WARN_AND_RETURN_UNLESS(pParaDefLib, oRes, L"paramLib为空！",L"GDMP",L"2023-10-20");

    const IParameterDefinition* pd = pParaDefLib->GetParameterDefinitionByUid(GetParameterDefinitionUid());

    UniIdentity ptId = pd->GetParameterTypeId();

    double internalValue = 0;
    if (ptId == PARAMETER_TYPE(Length))
    {
        internalValue = StringUtil::ToNumber<double>(displayString);
        oRes = IParameterValueDouble::Create(internalValue);
    }
    else if (ptId == PARAMETER_TYPE(Area))
    {
        internalValue = StringUtil::ToNumber<double>(displayString);
        internalValue *= 1E6; // 单位转换
        oRes = IParameterValueDouble::Create(internalValue);
    }
    else if (ptId == PARAMETER_TYPE(Volume))
    {
        internalValue = StringUtil::ToNumber<double>(displayString);
        internalValue *= 1E9; // 单位转换
        oRes = IParameterValueDouble::Create(internalValue);
    }
    else if (ptId == PARAMETER_TYPE(Text))
    {
        if (pd->GetStorageType() == ParameterStorageType::String)
        {
            oRes = IParameterValueString::Create(displayString);
        }
    }
    else if (ptId == PARAMETER_TYPE(Angle))
    {
        if (pd->GetUnitTypeId() == UNIT(Angle))
        {
            std::wstring newDisplayValue = displayString.substr(0, displayString.find_last_of(L"°"));
            internalValue = StringUtil::ToNumber<double>(newDisplayValue);
            internalValue = internalValue * gcmp::Constants::MATH_PI / 180;
            oRes = IParameterValueDouble::Create(internalValue);
        }
    }
    else if (ptId == PARAMETER_TYPE(Number))
    {
        int internalValueInt = StringUtil::ToNumber<int>(displayString);
        oRes = IParameterValueInt::Create(internalValueInt);
    }
    else if (ptId == PARAMETER_TYPE(Float))
    {
        double doubleValue = StringUtil::ToNumber<double>(displayString);
        oRes = IParameterValueDouble::Create(doubleValue);
    }
    else if (ptId == PARAMETER_TYPE(StandardCodeReference))
    {
#pragma warning(push)
#pragma warning(disable: 4996)
        const IStandardCodeItem* pCodeItem = IStandardCodeSystemProxy::Get()->GetStandardCodeItemByCode(displayString);
#pragma warning(pop)
        if (pCodeItem)
        {
            oRes = IParameterValueString::Create(displayString);
        }
    }
    else
    {
        DBG_WARN(L"暂未实现",L"GDMP",L"2023-10-20");
    }

    return oRes;
}

